package com.sinodata.bsm.center.dao;

import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.DetachedCriteria;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
import org.springframework.stereotype.Repository;
import org.springframework.util.Assert;

/**
 * 
 * <p>
 * Description: DAO根类
 * </p>
 * 
 * @author liulibo
 * @version 1.0
 * 
 * <p>
 * History:
 * 
 * Date Author Version Description
 * ---------------------------------------------------------------------------------
 * 2012-5-3 下午3:01:27 liulibo 1.0 To create
 * </p>
 * 
 * @since
 * @see
 */
@Repository
public class BaseDao extends HibernateDaoSupport {

    private final static Logger logger = LoggerFactory.getLogger(BaseDao.class);

    @Autowired
    public void setBaseDaoSessionFactory(SessionFactory sessionFactory) {
        super.setSessionFactory(sessionFactory);
    }

    /**
     * 删除一个实体
     * 
     * @param entity
     *            实体
     */
    public void delete(Object entity) {
        Assert.notNull(entity);
        getHibernateTemplate().delete(entity);
    }

    public Session getHibernateSession() {
        return this.getSession();
    }

    /**
     * 获得所有实体
     * 
     * @param entity
     *            实体
     * @return 实体列表
     */
    public List<?> findAll(final Class<?> entity) {
        return getHibernateTemplate().findByCriteria(DetachedCriteria.forClass(entity));
    }

    /**
     * 查找所有实体并返回所需要的行数区间
     * 
     * @param entity
     *            实体
     * @param first
     *            开始行
     * @param maxSize
     *            最大行数
     * @return 实体列表
     */
    public List<?> findAll(final Class<?> entity, final int first, final int maxSize) {
        return getHibernateTemplate().findByCriteria(DetachedCriteria.forClass(entity), first, maxSize);
    }

    /**
     * 根据id查找某个实体
     * 
     * @param entity
     *            实体
     * @param id
     *            id
     * @return 实体
     */
    public Object findById(Class<?> entity, Object id) {
        return getHibernateTemplate().get(entity, (java.io.Serializable) id);
    }

    /**
     * 保存一个实体
     * 
     * @param entity
     *            实体
     */
    public void save(Object entity) {
        getHibernateTemplate().save(entity);
    }

    /**
     * 更新一个实体
     * 
     * @param entity
     *            实体
     */
    public void update(Object entity) throws DataAccessException {
        getHibernateTemplate().merge(entity);
    }

    /**
     * flush session
     */
    public void flush() {
        getSession().flush();
    }

    /**
     * clear session
     */
    public void clear() {
        getSession().clear();
    }

    /**
     * 通过KEY查询一条记录
     * 
     * @param entity
     * @param keyName
     * @param keyValue
     * @return
     */
    public Object findByKey(final Class<?> entity, final String keyName, final Object keyValue) {
        try {
            List<?> result = getHibernateTemplate().find("from " + entity.getName() + " where " + keyName + " = ?", keyValue);
            if (result != null && result.size() > 0) {
                return result.get(0);
            }
        } catch (DataAccessException exception) {
            logger.error("查询数据库 " + entity.getName(), exception);
        }
        return null;
    }

    /**
     * 通过HQL查询一条记录,如果有多条记录则返回第一条记录
     * 
     * @param entity
     * @param hql
     * @return
     */
    public Object findObjectByHql(final Class<?> entity, final String hql) {
        try {
            List<?> result = getHibernateTemplate().find(hql);
            if (result != null && result.size() > 0) {
                return result.get(0);
            }
        } catch (DataAccessException exception) {
            logger.error("查询数据库 " + entity.getName(), exception);
        }
        return null;
    }

    /**
     * 通过HQL查询结果集
     * 
     * @param hql
     * @return
     */
    public List<?> findListByHql(final String hql) {
        try {
            List<?> result = getHibernateTemplate().find(hql);
            if (result != null && result.size() > 0) {
                return result;
            }
        } catch (DataAccessException exception) {
            logger.error("查询数据库 ", exception);
        }
        return null;
    }

    public List<?> findByNamedQuery(final String queryName, Object... values) {
        return getHibernateTemplate().findByNamedQuery(queryName, values);
    }

    /**
     * 保存或更新一个实体
     * 
     * @param entity
     *            实体
     */
    public void saveOrUpdate(Object entity) {
        Assert.notNull(entity);
        super.getHibernateTemplate().saveOrUpdate(entity);
    }

    /**
     * 批量保存或更新实体
     * 
     * @param entity
     *            实体LIST
     * @throws Exception
     * 
     */
    public void batchSaveOrUpdate(List<?> entity) {
        Session session = this.getSession();
        for (int i = 0; i < entity.size(); i++) {
            logger.debug("\n\n========>batchSaveOrUpdate numbers:" + i);
            session.saveOrUpdate(entity.get(i));
            if (i % 100 == 0 || i == (entity.size() - 1)) {
                session.flush();
                session.clear();
            }
        }
    }

    /**
     * 批量保存实体
     * 
     * @param entity
     *            实体LIST
     * @throws Exception
     * 
     */
    public void batchSave(List<?> entity) throws Exception {
        Session session = this.getSession();
        for (int i = 0; i < entity.size(); i++) {
            logger.debug("\n\n========>batchSave numbers:" + i);
            session.save(entity.get(i));
            if (i % 100 == 0 || i == (entity.size() - 1)) {
                session.flush();
                session.clear();
            }
        }
    }

    /**
     * 根据过滤条件过滤获取总数
     * 
     * @param hql
     * @param map
     * @return
     */
    public int getTotalCount(String hql, Map<String, String> map) {
        try {
            Query query = this.getSession().createQuery(hql);
            Iterator<Entry<String, String>> it = map.entrySet().iterator();
            while (it.hasNext()) {
                Entry<String, String> entry = it.next();
                query.setParameter(entry.getKey(), entry.getValue());
            }
            Integer i = (Integer) query.list().get(0);
            return i;
        } catch (RuntimeException re) {
            throw re;
        }
    }

}